﻿using l1cs.server.model;
using l1cs.server.model.gametime;
using l1cs.server.datatables;
using l1cs.server.model.Instance;
using System;
using MySql.Data.MySqlClient;
using System.Data;
using l1cs.server.serverpackets;
using l1cs.server.utils;
using System.Collections;

namespace l1cs.server
{
    public class HomeTownTimeController : L1GameTimeAdapter
    {
        private static Logger _log = Logger.getLogger( typeof( HomeTownTimeController ).FullName );

        private static HomeTownTimeController _instance;

        public static HomeTownTimeController getInstance()
        {
            if ( _instance == null )
            {
                _instance = new HomeTownTimeController();
                L1GameTimeClock.getInstance().addListener( _instance );
            }
            return _instance;
        }

        private HomeTownTimeController() { }

        
        override public void onDayChanged( L1GameTime time )
        {
            fixedProc( time );
        }

        private void fixedProc( L1GameTime time )
        {
            int day = time.getDateTime().Day;

            if ( day == 25 )
            {
                monthlyProc();
            }
            else
            {
                dailyProc();
            }
        }

        public void dailyProc()
        {
            _log.info( "ホームタウンシステム：日時処理開始" );
            TownTable.getInstance().updateTaxRate();
            TownTable.getInstance().updateSalesMoneyYesterday();
            TownTable.getInstance().load();
        }

        public void monthlyProc()
        {
            _log.info( "ホームタウンシステム：月時処理開始" );
            L1World.getInstance().setProcessingContributionTotal( true );
            ICollection players = L1World.getInstance().getAllPlayers();
            foreach ( L1PcInstance pc in players )
            {
                // DBにキャラクター情報を書き込む
                pc.save();
            }

            for ( int townId = 1; townId <= 10; townId++ )
            {
                String leaderName = totalContribution( townId );
                if ( leaderName != null )
                {
                    S_PacketBox packet = new S_PacketBox( S_PacketBox.MSG_TOWN_LEADER, leaderName );
                    foreach ( L1PcInstance pc in players )
                    {
                        if ( pc.getHomeTownId() == townId )
                        {
                            pc.setContribution( 0 );
                            pc.sendPackets( packet );
                        }
                    }
                }
            }
            TownTable.getInstance().load();

            foreach ( L1PcInstance pc in players )
            {
                if ( pc.getHomeTownId() == -1 )
                {
                    pc.setHomeTownId( 0 );
                }
                pc.setContribution( 0 );
                // DBにキャラクター情報を書き込む
                pc.save();
            }
            clearHomeTownID();
            L1World.getInstance().setProcessingContributionTotal( false );
        }

        private static String totalContribution( int townId )
        {
            int leaderId = 0;
            String leaderName = null;
            String sqlstr = @"SELECT objid, char_name FROM characters 
                                WHERE HomeTownID = ?1 
                                ORDER BY Contribution DESC";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd1 = new MySqlCommand( sqlstr );
                cmd1.Parameters.Add( "?1", MySqlDbType.Int32 ).Value = townId;
                DataTable dt1 = wrapper.GetDataTable( cmd1 );
                if ( dt1.Rows.Count > 0 )
                {
                    leaderId = SqlUtils.toInt( dt1.Rows[0]["objid"] );
                    leaderName = dt1.Rows[0]["char_name"] as String;
                }

                double totalContribution = 0;
                sqlstr = @"SELECT SUM(Contribution) AS TotalContribution FROM characters 
                         WHERE HomeTownID = ?1";
                MySqlCommand cmd2 = new MySqlCommand( sqlstr );
                cmd2.Parameters.Add( "?1", MySqlDbType.Int32 ).Value = townId;
                DataTable dt2 = wrapper.GetDataTable( cmd2 );
                if ( dt2.Rows.Count > 0 )
                {
                    totalContribution = SqlUtils.toInt( dt2.Rows[0]["TotalContribution"] );
                }

                double townFixTax = 0;
                sqlstr = "SELECT town_fix_tax FROM town WHERE town_id = ?1";
                MySqlCommand cmd3 = new MySqlCommand( sqlstr );
                cmd3.Parameters.Add( "?1", MySqlDbType.Int32 ).Value = townId;
                DataTable dt3 = wrapper.GetDataTable( cmd3 );
                if ( dt3.Rows.Count > 0 )
                {
                    townFixTax = SqlUtils.toInt( dt3.Rows[0]["town_fix_tax"] );
                }

                double contributionUnit = 0;
                if ( totalContribution != 0 )
                {
                    contributionUnit = Math.Floor( townFixTax / totalContribution * 100 ) / 100;
                }
                sqlstr = @"UPDATE characters SET 
                         Contribution = 0, 
                         Pay = Contribution * ?1 
                         WHERE HomeTownID   = ?2";
                MySqlCommand cmd4 = new MySqlCommand( sqlstr );
                cmd4.Parameters.Add( "?1", MySqlDbType.Int32 ).Value = contributionUnit;
                cmd4.Parameters.Add( "?2", MySqlDbType.Int32 ).Value = townId;
                wrapper.ExecNonQuery( cmd4 );

                sqlstr = @"UPDATE town SET 
                             leader_id             = ?1, 
                             leader_name           = ?2, 
                             tax_rate              = 0, 
                             tax_rate_reserved     = 0, 
                             sales_money           = 0, 
                             sales_money_yesterday = sales_money, 
                             town_tax              = 0, 
                             town_fix_tax          = 0 
                             WHERE town_id         = ?3";
                MySqlCommand cmd5 = new MySqlCommand( sqlstr );
                cmd5.Parameters.Add( "?1", MySqlDbType.Int32 ).Value = leaderId;
                cmd5.Parameters.Add( "?2", MySqlDbType.Int32 ).Value = leaderName;
                cmd5.Parameters.Add( "?3", MySqlDbType.Int32 ).Value = townId;
                wrapper.ExecNonQuery( cmd5 );
            }
            return leaderName;
        }

        private static void clearHomeTownID()
        {
            String sqlstr = "UPDATE characters SET HomeTownID = 0 WHERE HomeTownID = -1";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd = new MySqlCommand( sqlstr );
                wrapper.ExecNonQuery( cmd );
            }
        }

        /// <summary>
        /// 報酬を取得しクリアする。
        /// </summary>
        /// <param name="objid"></param>
        /// <returns>報酬</returns>
        public static int getPay( int objid )
        {
            int pay = 0;

            string sqlstr = "SELECT Pay FROM characters WHERE objid = ?1 FOR UPDATE";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd1 = new MySqlCommand( sqlstr );
                cmd1.Parameters.Add( "?1", MySqlDbType.Int32 ).Value = objid;
                Object obj = wrapper.ExecScaler( cmd1 );

                if ( obj != null && !( obj is DBNull ) )
                {
                    pay = SqlUtils.toInt( obj );
                }

                sqlstr = "UPDATE characters SET Pay = 0 WHERE objid = ?1";
                MySqlCommand cmd2 = new MySqlCommand( sqlstr );
                cmd1.Parameters.Add( "?1", MySqlDbType.Int32 ).Value = objid;
                wrapper.ExecNonQuery( cmd2 );
            }

            return pay;
        }
    }
}
